home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Tk / generic / tkImage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-31  |  21.8 KB  |  764 lines

  1. /* 
  2.  * tkImage.c --
  3.  *
  4.  *    This module implements the image protocol, which allows lots
  5.  *    of different kinds of images to be used in lots of different
  6.  *    widgets.
  7.  *
  8.  * Copyright (c) 1994 The Regents of the University of California.
  9.  * Copyright (c) 1994-1996 Sun Microsystems, Inc.
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  *
  14.  * SCCS: @(#) tkImage.c 1.11 96/03/01 17:19:28
  15.  */
  16.  
  17. #include "tkInt.h"
  18. #include "tkPort.h"
  19.  
  20. /*
  21.  * Each call to Tk_GetImage returns a pointer to one of the following
  22.  * structures, which is used as a token by clients (widgets) that
  23.  * display images.
  24.  */
  25.  
  26. typedef struct Image {
  27.     Tk_Window tkwin;        /* Window passed to Tk_GetImage (needed to
  28.                  * "re-get" the image later if the manager
  29.                  * changes). */
  30.     Display *display;        /* Display for tkwin.  Needed because when
  31.                  * the image is eventually freed tkwin may
  32.                  * not exist anymore. */
  33.     struct ImageMaster *masterPtr;
  34.                 /* Master for this image (identifiers image
  35.                  * manager, for example). */
  36.     ClientData instanceData;
  37.                 /* One word argument to pass to image manager
  38.                  * when dealing with this image instance. */
  39.     Tk_ImageChangedProc *changeProc;
  40.                 /* Code in widget to call when image changes
  41.                  * in a way that affects redisplay. */
  42.     ClientData widgetClientData;
  43.                 /* Argument to pass to changeProc. */
  44.     struct Image *nextPtr;    /* Next in list of all image instances
  45.                  * associated with the same name. */
  46.  
  47. } Image;
  48.  
  49. /*
  50.  * For each image master there is one of the following structures,
  51.  * which represents a name in the image table and all of the images
  52.  * instantiated from it.  Entries in mainPtr->imageTable point to
  53.  * these structures.
  54.  */
  55.  
  56. typedef struct ImageMaster {
  57.     Tk_ImageType *typePtr;    /* Information about image type.  NULL means
  58.                  * that no image manager owns this image:  the
  59.                  * image was deleted. */
  60.     ClientData masterData;    /* One-word argument to pass to image mgr
  61.                  * when dealing with the master, as opposed
  62.                  * to instances. */
  63.     int width, height;        /* Last known dimensions for image. */
  64.     Tcl_HashTable *tablePtr;    /* Pointer to hash table containing image
  65.                  * (the imageTable field in some TkMainInfo
  66.                  * structure). */
  67.     Tcl_HashEntry *hPtr;    /* Hash entry in mainPtr->imageTable for
  68.                  * this structure (used to delete the hash
  69.                  * entry). */
  70.     Image *instancePtr;        /* Pointer to first in list of instances
  71.                  * derived from this name. */
  72. } ImageMaster;
  73.  
  74. /*
  75.  * The following variable points to the first in a list of all known
  76.  * image types.
  77.  */
  78.  
  79. static Tk_ImageType *imageTypeList = NULL;
  80.  
  81. /*
  82.  * Prototypes for local procedures:
  83.  */
  84.  
  85. static void        DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr));
  86.  
  87. /*
  88.  *----------------------------------------------------------------------
  89.  *
  90.  * Tk_CreateImageType --
  91.  *
  92.  *    This procedure is invoked by an image manager to tell Tk about
  93.  *    a new kind of image and the procedures that manage the new type.
  94.  *    The procedure is typically invoked during Tcl_AppInit.
  95.  *
  96.  * Results:
  97.  *    None.
  98.  *
  99.  * Side effects:
  100.  *    The new image type is entered into a table used in the "image
  101.  *    create" command.
  102.  *
  103.  *----------------------------------------------------------------------
  104.  */
  105.  
  106. void
  107. Tk_CreateImageType(typePtr)
  108.     Tk_ImageType *typePtr;    /* Structure describing the type.  All of
  109.                  * the fields except "nextPtr" must be filled
  110.                  * in by caller.  Must not have been passed
  111.                  * to Tk_CreateImageType previously. */
  112. {
  113.     Tk_ImageType *typePtr2;
  114.  
  115.     typePtr2 = (Tk_ImageType *) ckalloc(sizeof(Tk_ImageType));
  116.     *typePtr2 = *typePtr;
  117.     typePtr2->name = (char *) ckalloc((unsigned) (strlen(typePtr->name) + 1));
  118.     strcpy(typePtr2->name, typePtr->name);
  119.     typePtr2->nextPtr = imageTypeList;
  120.     imageTypeList = typePtr2;
  121. }
  122.  
  123. /*
  124.  *----------------------------------------------------------------------
  125.  *
  126.  * Tk_ImageCmd --
  127.  *
  128.  *    This procedure is invoked to process the "image" Tcl command.
  129.  *    See the user documentation for details on what it does.
  130.  *
  131.  * Results:
  132.  *    A standard Tcl result.
  133.  *
  134.  * Side effects:
  135.  *    See the user documentation.
  136.  *
  137.  *----------------------------------------------------------------------
  138.  */
  139.  
  140. int
  141. Tk_ImageCmd(clientData, interp, argc, argv)
  142.     ClientData clientData;    /* Main window associated with interpreter. */
  143.     Tcl_Interp *interp;        /* Current interpreter. */
  144.     int argc;            /* Number of arguments. */
  145.     char **argv;        /* Argument strings. */
  146. {
  147.     TkWindow *winPtr = (TkWindow *) clientData;
  148.     int c, i, new, firstOption;
  149.     size_t length;
  150.     Tk_ImageType *typePtr;
  151.     ImageMaster *masterPtr;
  152.     Image *imagePtr;
  153.     Tcl_HashEntry *hPtr;
  154.     Tcl_HashSearch search;
  155.     char idString[30], *name;
  156.     static int id = 0;
  157.  
  158.     if (argc < 2) {
  159.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  160.         " option ?args?\"", (char *) NULL);
  161.     return TCL_ERROR;
  162.     }
  163.     c = argv[1][0];
  164.     length = strlen(argv[1]);
  165.     if ((c == 'c') && (strncmp(argv[1], "create", length) == 0)) {
  166.     if (argc < 3) {
  167.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  168.             " create type ?name? ?options?\"", (char *) NULL);
  169.         return TCL_ERROR;
  170.     }
  171.     c = argv[2][0];
  172.  
  173.     /*
  174.      * Look up the image type.
  175.      */
  176.  
  177.     for (typePtr = imageTypeList; typePtr != NULL;
  178.         typePtr = typePtr->nextPtr) {
  179.         if ((c == typePtr->name[0])
  180.             && (strcmp(argv[2], typePtr->name) == 0)) {
  181.         break;
  182.         }
  183.     }
  184.     if (typePtr == NULL) {
  185.         Tcl_AppendResult(interp, "image type \"", argv[2],
  186.             "\" doesn't exist", (char *) NULL);
  187.         return TCL_ERROR;
  188.     }
  189.  
  190.     /*
  191.      * Figure out a name to use for the new image.
  192.      */
  193.  
  194.     if ((argc == 3) || (argv[3][0] == '-')) {
  195.         id++;
  196.         sprintf(idString, "image%d", id);
  197.         name = idString;
  198.         firstOption = 3;
  199.     } else {
  200.         name = argv[3];
  201.         firstOption = 4;
  202.     }
  203.  
  204.     /*
  205.      * Create the data structure for the new image.
  206.      */
  207.  
  208.     hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, name, &new);
  209.     if (new) {
  210.         masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster));
  211.         masterPtr->typePtr = NULL;
  212.         masterPtr->masterData = NULL;
  213.         masterPtr->width = masterPtr->height = 1;
  214.         masterPtr->tablePtr = &winPtr->mainPtr->imageTable;
  215.         masterPtr->hPtr = hPtr;
  216.         masterPtr->instancePtr = NULL;
  217.         Tcl_SetHashValue(hPtr, masterPtr);
  218.     } else {
  219.         /*
  220.          * An image already exists by this name.  Disconnect the
  221.          * instances from the master.
  222.          */
  223.  
  224.         masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  225.         if (masterPtr->typePtr != NULL) {
  226.         for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  227.             imagePtr = imagePtr->nextPtr) {
  228.            (*masterPtr->typePtr->freeProc)(
  229.                imagePtr->instanceData, imagePtr->display);
  230.            (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0,
  231.             masterPtr->width, masterPtr->height, masterPtr->width,
  232.             masterPtr->height);
  233.         }
  234.         (*masterPtr->typePtr->deleteProc)(masterPtr->masterData);
  235.         masterPtr->typePtr = NULL;
  236.         }
  237.     }
  238.  
  239.     /*
  240.      * Call the image type manager so that it can perform its own
  241.      * initialization, then re-"get" for any existing instances of
  242.      * the image.
  243.      */
  244.  
  245.     if ((*typePtr->createProc)(interp, name, argc-firstOption,
  246.         argv+firstOption, typePtr, (Tk_ImageMaster) masterPtr,
  247.         &masterPtr->masterData) != TCL_OK) {
  248.         DeleteImage(masterPtr);
  249.         return TCL_ERROR;
  250.     }
  251.     masterPtr->typePtr = typePtr;
  252.     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  253.         imagePtr = imagePtr->nextPtr) {
  254.        imagePtr->instanceData = (*typePtr->getProc)(
  255.            imagePtr->tkwin, masterPtr->masterData);
  256.     }
  257. #ifdef STk_CODE
  258.     STk_sharp_dot_result(interp, 
  259.                   Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr));
  260. #else
  261.     interp->result = Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr);
  262. #endif
  263.     } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
  264.     for (i = 2; i < argc; i++) {
  265.         hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[i]);
  266.         if (hPtr == NULL) {
  267.         Tcl_AppendResult(interp, "image \"", argv[i],
  268.             "\" doesn't exist", (char *) NULL);
  269.         return TCL_ERROR;
  270.         }
  271.         masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  272.         DeleteImage(masterPtr);
  273.     }
  274.     } else if ((c == 'h') && (strncmp(argv[1], "height", length) == 0)) {
  275.     if (argc != 3) {
  276.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  277.             " height name\"", (char *) NULL);
  278.         return TCL_ERROR;
  279.     }
  280.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]);
  281.     if (hPtr == NULL) {
  282.         Tcl_AppendResult(interp, "image \"", argv[2],
  283.             "\" doesn't exist", (char *) NULL);
  284.         return TCL_ERROR;
  285.     }
  286.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  287.     sprintf(interp->result, "%d", masterPtr->height);
  288.     } else if ((c == 'n') && (strncmp(argv[1], "names", length) == 0)) {
  289.     if (argc != 2) {
  290.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  291.             " names\"", (char *) NULL);
  292.         return TCL_ERROR;
  293.     }
  294. #ifdef STk_CODE
  295.         Tcl_AppendResult(interp, "(", NULL);
  296. #endif
  297.     for (hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);
  298.         hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
  299.         Tcl_AppendElement(interp, Tcl_GetHashKey(
  300.             &winPtr->mainPtr->imageTable, hPtr));
  301.     }
  302. #ifdef STk_CODE
  303.         Tcl_AppendResult(interp, ")", NULL);
  304. #endif
  305.     } else if ((c == 't') && (strcmp(argv[1], "type") == 0)) {
  306.     if (argc != 3) {
  307.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  308.             " type name\"", (char *) NULL);
  309.         return TCL_ERROR;
  310.     }
  311.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]);
  312.     if (hPtr == NULL) {
  313.         Tcl_AppendResult(interp, "image \"", argv[2],
  314.             "\" doesn't exist", (char *) NULL);
  315.         return TCL_ERROR;
  316.     }
  317.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  318.     if (masterPtr->typePtr != NULL) {
  319.         interp->result = masterPtr->typePtr->name;
  320.     }
  321.     } else if ((c == 't') && (strcmp(argv[1], "types") == 0)) {
  322.     if (argc != 2) {
  323.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  324.             " types\"", (char *) NULL);
  325.         return TCL_ERROR;
  326.     }
  327.     for (typePtr = imageTypeList; typePtr != NULL;
  328.         typePtr = typePtr->nextPtr) {
  329.         Tcl_AppendElement(interp, typePtr->name);
  330.     }
  331.     } else if ((c == 'w') && (strncmp(argv[1], "width", length) == 0)) {
  332.     if (argc != 3) {
  333.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  334.             " width name\"", (char *) NULL);
  335.         return TCL_ERROR;
  336.     }
  337.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]);
  338.     if (hPtr == NULL) {
  339.         Tcl_AppendResult(interp, "image \"", argv[2],
  340.             "\" doesn't exist", (char *) NULL);
  341.         return TCL_ERROR;
  342.     }
  343.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  344.     sprintf(interp->result, "%d", masterPtr->width);
  345.     } else {
  346.     Tcl_AppendResult(interp, "bad option \"", argv[1],
  347.         "\": must be create, delete, height, names, type, types,",
  348.         " or width", (char *) NULL);
  349.     return TCL_ERROR;
  350.     }
  351.     return TCL_OK;
  352. }
  353.  
  354. /*
  355.  *----------------------------------------------------------------------
  356.  *
  357.  * Tk_ImageChanged --
  358.  *
  359.  *    This procedure is called by an image manager whenever something
  360.  *    has happened that requires the image to be redrawn (some of its
  361.  *    pixels have changed, or its size has changed).
  362.  *
  363.  * Results:
  364.  *    None.
  365.  *
  366.  * Side effects:
  367.  *    Any widgets that display the image are notified so that they
  368.  *    can redisplay themselves as appropriate.
  369.  *
  370.  *----------------------------------------------------------------------
  371.  */
  372.  
  373. void
  374. Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth,
  375.     imageHeight)
  376.     Tk_ImageMaster imageMaster;    /* Image that needs redisplay. */
  377.     int x, y;            /* Coordinates of upper-left pixel of
  378.                  * region of image that needs to be
  379.                  * redrawn. */
  380.     int width, height;        /* Dimensions (in pixels) of region of
  381.                  * image to redraw.  If either dimension
  382.                  * is zero then the image doesn't need to
  383.                  * be redrawn (perhaps all that happened is
  384.                  * that its size changed). */
  385.     int imageWidth, imageHeight;/* New dimensions of image. */
  386. {
  387.     ImageMaster *masterPtr = (ImageMaster *) imageMaster;
  388.     Image *imagePtr;
  389.  
  390.     masterPtr->width = imageWidth;
  391.     masterPtr->height = imageHeight;
  392.     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  393.         imagePtr = imagePtr->nextPtr) {
  394.     (*imagePtr->changeProc)(imagePtr->widgetClientData, x, y,
  395.         width, height, imageWidth, imageHeight);
  396.     }
  397. }
  398.  
  399. /*
  400.  *----------------------------------------------------------------------
  401.  *
  402.  * Tk_NameOfImage --
  403.  *
  404.  *    Given a token for an image master, this procedure returns
  405.  *    the name of the image.
  406.  *
  407.  * Results:
  408.  *    The return value is the string name for imageMaster.
  409.  *
  410.  * Side effects:
  411.  *    None.
  412.  *
  413.  *----------------------------------------------------------------------
  414.  */
  415.  
  416. char *
  417. Tk_NameOfImage(imageMaster)
  418.     Tk_ImageMaster imageMaster;        /* Token for image. */
  419. {
  420.     ImageMaster *masterPtr = (ImageMaster *) imageMaster;
  421.  
  422.     return Tcl_GetHashKey(masterPtr->tablePtr, masterPtr->hPtr);
  423. }
  424.  
  425. /*
  426.  *----------------------------------------------------------------------
  427.  *
  428.  * Tk_GetImage --
  429.  *
  430.  *    This procedure is invoked by a widget when it wants to use
  431.  *    a particular image in a particular window.
  432.  *
  433.  * Results:
  434.  *    The return value is a token for the image.  If there is no image
  435.  *    by the given name, then NULL is returned and an error message is
  436.  *    left in interp->result.
  437.  *
  438.  * Side effects:
  439.  *    Tk records the fact that the widget is using the image, and
  440.  *    it will invoke changeProc later if the widget needs redisplay
  441.  *    (i.e. its size changes or some of its pixels change).  The
  442.  *    caller must eventually invoke Tk_FreeImage when it no longer
  443.  *    needs the image.
  444.  *
  445.  *----------------------------------------------------------------------
  446.  */
  447.  
  448. Tk_Image
  449. Tk_GetImage(interp, tkwin, name, changeProc, clientData)
  450.     Tcl_Interp *interp;        /* Place to leave error message if image
  451.                  * can't be found. */
  452.     Tk_Window tkwin;        /* Token for window in which image will
  453.                  * be used. */
  454.     char *name;            /* Name of desired image. */
  455.     Tk_ImageChangedProc *changeProc;
  456.                 /* Procedure to invoke when redisplay is
  457.                  * needed because image's pixels or size
  458.                  * changed. */
  459.     ClientData clientData;    /* One-word argument to pass to damageProc. */
  460. {
  461.     Tcl_HashEntry *hPtr;
  462.     ImageMaster *masterPtr;
  463.     Image *imagePtr;
  464.  
  465.     hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->imageTable, name);
  466.     if (hPtr == NULL) {
  467.     goto noSuchImage;
  468.     }
  469.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  470.     if (masterPtr->typePtr == NULL) {
  471.     goto noSuchImage;
  472.     }
  473.     imagePtr = (Image *) ckalloc(sizeof(Image));
  474.     imagePtr->tkwin = tkwin;
  475.     imagePtr->display = Tk_Display(tkwin);
  476.     imagePtr->masterPtr = masterPtr;
  477.     imagePtr->instanceData =
  478.         (*masterPtr->typePtr->getProc)(tkwin, masterPtr->masterData);
  479.     imagePtr->changeProc = changeProc;
  480.     imagePtr->widgetClientData = clientData;
  481.     imagePtr->nextPtr = masterPtr->instancePtr;
  482.     masterPtr->instancePtr = imagePtr;
  483.     return (Tk_Image) imagePtr;
  484.  
  485.     noSuchImage:
  486.     Tcl_AppendResult(interp, "image \"", name, "\" doesn't exist",
  487.         (char *) NULL);
  488.     return NULL;
  489. }
  490.  
  491. /*
  492.  *----------------------------------------------------------------------
  493.  *
  494.  * Tk_FreeImage --
  495.  *
  496.  *    This procedure is invoked by a widget when it no longer needs
  497.  *    an image acquired by a previous call to Tk_GetImage.  For each
  498.  *    call to Tk_GetImage there must be exactly one call to Tk_FreeImage.
  499.  *
  500.  * Results:
  501.  *    None.
  502.  *
  503.  * Side effects:
  504.  *    The association between the image and the widget is removed.
  505.  *
  506.  *----------------------------------------------------------------------
  507.  */
  508.  
  509. void
  510. Tk_FreeImage(image)
  511.     Tk_Image image;        /* Token for image that is no longer
  512.                  * needed by a widget. */
  513. {
  514.     Image *imagePtr = (Image *) image;
  515.     ImageMaster *masterPtr = imagePtr->masterPtr;
  516.     Image *prevPtr;
  517.  
  518.     /*
  519.      * Clean up the particular instance.
  520.      */
  521.  
  522.     if (masterPtr->typePtr != NULL) {
  523.     (*masterPtr->typePtr->freeProc)(imagePtr->instanceData,
  524.         imagePtr->display);
  525.     }
  526.     prevPtr = masterPtr->instancePtr;
  527.     if (prevPtr == imagePtr) {
  528.     masterPtr->instancePtr = imagePtr->nextPtr;
  529.     } else {
  530.     while (prevPtr->nextPtr != imagePtr) {
  531.         prevPtr = prevPtr->nextPtr;
  532.     }
  533.     prevPtr->nextPtr = imagePtr->nextPtr;
  534.     }
  535.     ckfree((char *) imagePtr);
  536.  
  537.     /* 
  538.      * If there are no more instances left for the master, and if the
  539.      * master image has been deleted, then delete the master too.
  540.      */
  541.  
  542.     if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) {
  543.     Tcl_DeleteHashEntry(masterPtr->hPtr);
  544.     ckfree((char *) masterPtr);
  545.     }
  546. }
  547.  
  548. /*
  549.  *----------------------------------------------------------------------
  550.  *
  551.  * Tk_RedrawImage --
  552.  *
  553.  *    This procedure is called by widgets that contain images in order
  554.  *    to redisplay an image on the screen or an off-screen pixmap.
  555.  *
  556.  * Results:
  557.  *    None.
  558.  *
  559.  * Side effects:
  560.  *    The image's manager is notified, and it redraws the desired
  561.  *    portion of the image before returning.
  562.  *
  563.  *----------------------------------------------------------------------
  564.  */
  565.  
  566. void
  567. Tk_RedrawImage(image, imageX, imageY, width, height, drawable,
  568.     drawableX, drawableY)
  569.     Tk_Image image;        /* Token for image to redisplay. */
  570.     int imageX, imageY;        /* Upper-left pixel of region in image that
  571.                  * needs to be redisplayed. */
  572.     int width, height;        /* Dimensions of region to redraw. */
  573.     Drawable drawable;        /* Drawable in which to display image
  574.                  * (window or pixmap).  If this is a pixmap,
  575.                  * it must have the same depth as the window
  576.                  * used in the Tk_GetImage call for the
  577.                  * image. */
  578.     int drawableX, drawableY;    /* Coordinates in drawable that correspond
  579.                  * to imageX and imageY. */
  580. {
  581.     Image *imagePtr = (Image *) image;
  582.  
  583.     if (imagePtr->masterPtr->typePtr == NULL) {
  584.     /*
  585.      * No master for image, so nothing to display.
  586.      */
  587.  
  588.     return;
  589.     }
  590.  
  591.     /*
  592.      * Clip the redraw area to the area of the image.
  593.      */
  594.  
  595.     if (imageX < 0) {
  596.     width += imageX;
  597.     drawableX -= imageX;
  598.     imageX = 0;
  599.     }
  600.     if (imageY < 0) {
  601.     height += imageY;
  602.     drawableY -= imageY;
  603.     imageY = 0;
  604.     }
  605.     if ((imageX + width) > imagePtr->masterPtr->width) {
  606.     width = imagePtr->masterPtr->width - imageX;
  607.     }
  608.     if ((imageY + height) > imagePtr->masterPtr->height) {
  609.     height = imagePtr->masterPtr->height - imageY;
  610.     }
  611.     (*imagePtr->masterPtr->typePtr->displayProc)(
  612.         imagePtr->instanceData, imagePtr->display, drawable,
  613.         imageX, imageY, width, height, drawableX, drawableY);
  614. }
  615.  
  616. /*
  617.  *----------------------------------------------------------------------
  618.  *
  619.  * Tk_SizeOfImage --
  620.  *
  621.  *    This procedure returns the current dimensions of an image.
  622.  *
  623.  * Results:
  624.  *    The width and height of the image are returned in *widthPtr
  625.  *    and *heightPtr.
  626.  *
  627.  * Side effects:
  628.  *    None.
  629.  *
  630.  *----------------------------------------------------------------------
  631.  */
  632.  
  633. void
  634. Tk_SizeOfImage(image, widthPtr, heightPtr)
  635.     Tk_Image image;        /* Token for image whose size is wanted. */
  636.     int *widthPtr;        /* Return width of image here. */
  637.     int *heightPtr;        /* Return height of image here. */
  638. {
  639.     Image *imagePtr = (Image *) image;
  640.  
  641.     *widthPtr = imagePtr->masterPtr->width;
  642.     *heightPtr = imagePtr->masterPtr->height;
  643. }
  644.  
  645. /*
  646.  *----------------------------------------------------------------------
  647.  *
  648.  * Tk_DeleteImage --
  649.  *
  650.  *    Given the name of an image, this procedure destroys the
  651.  *    image.
  652.  *
  653.  * Results:
  654.  *    None.
  655.  *
  656.  * Side effects:
  657.  *    The image is destroyed; existing instances will display as
  658.  *    blank areas.  If no such image exists then the procedure does
  659.  *    nothing.
  660.  *
  661.  *----------------------------------------------------------------------
  662.  */
  663.  
  664. void
  665. Tk_DeleteImage(interp, name)
  666.     Tcl_Interp *interp;        /* Interpreter in which the image was
  667.                  * created. */
  668.     char *name;            /* Name of image. */
  669. {
  670.     Tcl_HashEntry *hPtr;
  671.     Tcl_CmdInfo info;
  672.     TkWindow *winPtr;
  673.  
  674.     if (Tcl_GetCommandInfo(interp, "winfo", &info) == 0) {
  675.     return;
  676.     }
  677.     winPtr = (TkWindow *) info.clientData;
  678.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
  679.     if (hPtr == NULL) {
  680.     return;
  681.     }
  682.     DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr));
  683. }
  684.  
  685. /*
  686.  *----------------------------------------------------------------------
  687.  *
  688.  * DeleteImage --
  689.  *
  690.  *    This procedure is responsible for deleting an image.
  691.  *
  692.  * Results:
  693.  *    None.
  694.  *
  695.  * Side effects:
  696.  *    The connection is dropped between instances of this image and
  697.  *    an image master.  Image instances will redisplay themselves
  698.  *    as empty areas, but existing instances will not be deleted.
  699.  *
  700.  *----------------------------------------------------------------------
  701.  */
  702.  
  703. static void
  704. DeleteImage(masterPtr)
  705.     ImageMaster *masterPtr;    /* Pointer to main data structure for image. */
  706. {
  707.     Image *imagePtr;
  708.     Tk_ImageType *typePtr;
  709.  
  710.     typePtr = masterPtr->typePtr;
  711.     masterPtr->typePtr = NULL;
  712.     if (typePtr != NULL) {
  713.     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  714.         imagePtr = imagePtr->nextPtr) {
  715.        (*typePtr->freeProc)(imagePtr->instanceData,
  716.            imagePtr->display);
  717.        (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0,
  718.             masterPtr->width, masterPtr->height, masterPtr->width,
  719.             masterPtr->height);
  720.     }
  721.     (*typePtr->deleteProc)(masterPtr->masterData);
  722.     }
  723.     if (masterPtr->instancePtr == NULL) {
  724.     Tcl_DeleteHashEntry(masterPtr->hPtr);
  725.     ckfree((char *) masterPtr);
  726.     }
  727. }
  728.  
  729. /*
  730.  *----------------------------------------------------------------------
  731.  *
  732.  * TkDeleteAllImages --
  733.  *
  734.  *    This procedure is called when an application is deleted.  It
  735.  *    calls back all of the managers for all images so that they
  736.  *    can cleanup, then it deletes all of Tk's internal information
  737.  *    about images.
  738.  *
  739.  * Results:
  740.  *    None.
  741.  *
  742.  * Side effects:
  743.  *    All information for all images gets deleted.
  744.  *
  745.  *----------------------------------------------------------------------
  746.  */
  747.  
  748. void
  749. TkDeleteAllImages(mainPtr)
  750.     TkMainInfo *mainPtr;    /* Structure describing application that is
  751.                  * going away. */
  752. {
  753.     Tcl_HashSearch search;
  754.     Tcl_HashEntry *hPtr;
  755.     ImageMaster *masterPtr;
  756.  
  757.     for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search);
  758.         hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
  759.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  760.     DeleteImage(masterPtr);
  761.     }
  762.     Tcl_DeleteHashTable(&mainPtr->imageTable);
  763. }
  764.